home *** CD-ROM | disk | FTP | other *** search
/ Chip 2006 June / CHIP 2006-06.2.iso / program / freeware / ubrowser.exe / ubrowser / embeddedbrowser.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-02-21  |  19.4 KB  |  659 lines

  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  uBrowser - a program that illustrates one way of embedding the
  4. //  Mozilla Gecko (tm) Rendering Engine in an application, grabbing the
  5. //  rendered output and displaying it on the surface of a 3D polygon as
  6. //  texture in an OpenGL (tm) application.
  7. //
  8. //  uBrowser is free software; you can redistribute it and/or modify
  9. //  it under the terms of the GNU General Public License as published by
  10. //  the Free Software Foundation; either version 2 of the License, or
  11. //  (at your option) any later version.
  12. //
  13. //  uBrowser is distributed in the hope that it will be useful,
  14. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. //  GNU General Public License for more details.
  17. //
  18. //  You should have received a copy of the GNU General Public License
  19. //  along with uBrowser; if not, write to the Free Software
  20. //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  21. //
  22. //  Original code:  Copyright 2005 Linden Research Inc.
  23. //                  http://www.lindenlab.com
  24. //
  25. //  Primary author and site maintainer: Callum Prentice (callum@ubrowser.com)
  26. //
  27. //  See contributors.txt or http://ubrowser.com for a list of contributors
  28. //  without whose generous donation of time and effort, this application
  29. //  would not have been possible.
  30. //
  31. ////////////////////////////////////////////////////////////////////////////////
  32. #include "embeddedbrowser.h"
  33.  
  34. // annoying, harmless warning we can't get rid of in MSVC.net
  35. // (no matching operator delete found; memory will not be freed if initialization throws an exception)
  36. #pragma warning ( disable : 4291 )
  37.  
  38. #include "nsCWebBrowser.h"
  39. #include "nsGUIEvent.h"
  40. #include "nsICaret.h"
  41. #include "nsIContent.h"
  42. #include "nsIDOMDocument.h"
  43. #include "nsIDOMElement.h"
  44. #include "nsIDOMWindow.h"
  45. #include "nsIDocShell.h"
  46. #include "nsIDocShellTreeItem.h"
  47. #include "nsIDocument.h"
  48. #include "nsIFrame.h"
  49. #include "nsIInterfaceRequestorUtils.h"
  50. #include "nsIScrollableView.h"
  51. #include "nsISelection.h"
  52. #include "nsISelectionController.h"
  53. #include "nsIWebBrowserChrome.h"
  54. #include "nsIWebBrowserChromeFocus.h"
  55. #include "nsIWebBrowserFocus.h"
  56. #include "nsPresContext.h"
  57. #include "nsProfileDirServiceProvider.h"
  58. #include "nsXPCOMGlue.h"
  59. #include "nsXULAppAPI.h"
  60.  
  61. ////////////////////////////////////////////////////////////////////////////////
  62. //
  63. embeddedBrowser::embeddedBrowser() :
  64.     mEmbeddedBrowserWindow( 0 ),
  65.     mWebBrowser( nsnull ),
  66.     mBaseWindow( nsnull ),
  67.     mWebNav( nsnull ),
  68.     mBrowserWidth( 0 ),
  69.     mBrowserHeight( 0 ),
  70.     mBrowserDepth( 4 ),
  71.     mPageBuffer( 0 ),
  72.     mErrorMessage( "" )
  73. {
  74. };
  75.  
  76. ////////////////////////////////////////////////////////////////////////////////
  77. //
  78. embeddedBrowser::~embeddedBrowser()
  79. {
  80.     if ( mEmbeddedBrowserWindow )
  81.     {
  82.         mEmbeddedBrowserWindow->Release();
  83.         mEmbeddedBrowserWindow = nsnull;
  84.     };
  85.  
  86.     if ( mWebNav )
  87.     {
  88.         mWebNav->Stop ( nsIWebNavigation::STOP_ALL );
  89.         mWebNav = nsnull;
  90.     };
  91.  
  92.     if ( mBaseWindow )
  93.     {
  94.         mBaseWindow->Destroy();
  95.         mBaseWindow = nsnull;
  96.     };
  97.  
  98.     mWebBrowser = nsnull;
  99.  
  100.     if ( mPageBuffer )
  101.     {
  102.         delete[] mPageBuffer;
  103.         mPageBuffer = 0;
  104.     };
  105.  
  106.     XRE_TermEmbedding();
  107. };
  108.  
  109. ////////////////////////////////////////////////////////////////////////////////
  110. //
  111. PRBool embeddedBrowser::init( std::string appBaseDir, PRInt16 browserWidthIn, PRInt16 browserHeightIn )
  112. {
  113.     mBrowserWidth = browserWidthIn;
  114.     mBrowserHeight = browserHeightIn;
  115.  
  116.     std::string appDir( appBaseDir );
  117.     std::string xulRuntimeDir( appBaseDir );
  118.     std::string profileDir( appBaseDir );
  119.  
  120.     nsCOMPtr< nsILocalFile > xuldir;
  121.     nsresult result = NS_NewNativeLocalFile( nsCString( xulRuntimeDir.c_str() ), PR_FALSE, getter_AddRefs( xuldir ) );
  122.     if ( NS_FAILED( result ) )
  123.     {
  124.         setErrorMessage( "NS_NewNativeLocalFile failed(xuldir)" );
  125.         return PR_FALSE;
  126.     };
  127.  
  128.     nsCOMPtr< nsILocalFile > appdir;
  129.     result = NS_NewNativeLocalFile( nsCString( appDir.c_str() ), PR_FALSE, getter_AddRefs( appdir ) );
  130.     if ( NS_FAILED( result ) )
  131.     {
  132.         setErrorMessage( "NS_NewNativeLocalFile failed(appdir)" );
  133.         return PR_FALSE;
  134.     };
  135.  
  136.     result = XRE_InitEmbedding( xuldir, appdir, nsnull, nsnull, 0 );
  137.     if ( NS_FAILED( result ) )
  138.     {
  139.         setErrorMessage( "XRE_InitEmbedding failed" );
  140.         return PR_FALSE;
  141.     };
  142.  
  143.     nsCOMPtr< nsILocalFile > appDataDir;
  144.     NS_NewNativeLocalFile( nsDependentCString( profileDir.c_str() ), PR_TRUE, getter_AddRefs( appDataDir ) );
  145.  
  146.     // this probably ought to be a parameter!
  147.     appDataDir->Append( NS_LITERAL_STRING( "xreprofile" ) );
  148.     nsCOMPtr< nsILocalFile > localAppDataDir( do_QueryInterface( appDataDir ) );
  149.  
  150.     nsCOMPtr< nsProfileDirServiceProvider > locProvider;
  151.     NS_NewProfileDirServiceProvider( PR_TRUE, getter_AddRefs( locProvider ) );
  152.     if ( ! locProvider )
  153.     {
  154.         setErrorMessage( "NS_NewProfileDirServiceProvider failed" );
  155.         XRE_TermEmbedding();
  156.         return PR_FALSE;
  157.     };
  158.  
  159.     result = locProvider->Register();
  160.     if ( NS_FAILED( result ) )
  161.     {
  162.         setErrorMessage( "locProvider->Register() failed" );
  163.         XRE_TermEmbedding();
  164.         return PR_FALSE;
  165.     };
  166.  
  167.     result = locProvider->SetProfileDir( localAppDataDir );
  168.     if ( NS_FAILED( result ) )
  169.     {
  170.         setErrorMessage( "locProvider->SetProfileDir() failed" );
  171.         XRE_TermEmbedding();
  172.         return PR_FALSE;
  173.     };
  174.  
  175.     return PR_TRUE;
  176. };
  177.  
  178. ////////////////////////////////////////////////////////////////////////////////
  179. //
  180. PRBool embeddedBrowser::createWindow( void* browserWindowHandleIn )
  181. {
  182.     nsresult result = NS_OK;
  183.  
  184.     mWebBrowser = do_CreateInstance( NS_WEBBROWSER_CONTRACTID, &result );
  185.     if ( NS_FAILED( result ) || ! mWebBrowser )
  186.     {
  187.         setErrorMessage( "mWebBrowser = do_CreateInstance( NS_WEBBROWSER_CONTRACTID, &result ) failed" );
  188.         return PR_FALSE;
  189.     };
  190.  
  191.     mWebNav = do_QueryInterface( mWebBrowser, &result );
  192.     if ( NS_FAILED( result ) || ! mWebNav )
  193.     {
  194.         setErrorMessage( "mWebNav = do_QueryInterface( mWebBrowser, &result ) failed" );
  195.         return PR_FALSE;
  196.     };
  197.  
  198.  
  199.     mEmbeddedBrowserWindow = new embeddedBrowserWindow;
  200.     if( mEmbeddedBrowserWindow == nsnull )
  201.     {
  202.         setErrorMessage( "unable to create an instance on the embedded browser window" );
  203.         return PR_FALSE;
  204.     };
  205.  
  206.     mEmbeddedBrowserWindow->Init( this, mWebBrowser );
  207.     mEmbeddedBrowserWindow->AddRef();
  208.  
  209. ///// NOT SURE IF WE NEED THIS     SetWebBrowser( mWebBrowser );
  210.  
  211.     mWebBrowser->SetContainerWindow( NS_STATIC_CAST( nsIWebBrowserChrome*, mEmbeddedBrowserWindow ) );
  212.  
  213.     nsCOMPtr< nsIDocShellTreeItem > dsti = do_QueryInterface( mWebBrowser );
  214.     dsti->SetItemType( nsIDocShellTreeItem::typeContentWrapper );
  215.  
  216.     mBaseWindow = do_QueryInterface( mWebBrowser, &result );
  217.     if ( NS_FAILED( result ) || ! mBaseWindow )
  218.     {
  219.         setErrorMessage( "mBaseWindow = do_QueryInterface( mWebBrowser, &result ) failed" );
  220.         return PR_FALSE;
  221.     };
  222.  
  223.     result = mBaseWindow->InitWindow( browserWindowHandleIn, nsnull, 0, 0, mBrowserWidth , mBrowserHeight );
  224.     if ( NS_FAILED( result ) )
  225.     {
  226.         setErrorMessage( "mBaseWindow->InitWindow( ... ) failed" );
  227.         return PR_FALSE;
  228.     };
  229.  
  230.     result = mBaseWindow->Create();
  231.     if ( NS_FAILED( result ) )
  232.     {
  233.         setErrorMessage( "mBaseWindow->Create() failed" );
  234.         return PR_FALSE;
  235.     };
  236.  
  237.     nsWeakPtr weakling( do_GetWeakReference( NS_STATIC_CAST( nsIWebProgressListener*, mEmbeddedBrowserWindow ) ) );
  238.     mWebBrowser->AddWebBrowserListener( weakling, NS_GET_IID( nsIWebProgressListener ) );
  239.  
  240.     mBaseWindow->SetVisibility( PR_FALSE );
  241.     mBaseWindow->SetPosition( 8000, -6000 );
  242.  
  243.     return PR_TRUE;
  244. };
  245.  
  246. ////////////////////////////////////////////////////////////////////////////////
  247. // change the size of the browser
  248. PRBool embeddedBrowser::setSize( PRInt16 widthIn, PRInt16 heightIn, PRBool repaintIn )
  249. {
  250.     if ( mBaseWindow )
  251.     {
  252.         // if there is a buffer already, get rid of it (it will get created as required in grabWindow())
  253.         if ( mPageBuffer )
  254.         {
  255.             delete[] mPageBuffer;
  256.             mPageBuffer = 0;
  257.         };
  258.  
  259.         // record new size
  260.         mBrowserWidth = widthIn;
  261.         mBrowserHeight = heightIn;
  262.  
  263.         // tell Mozilla about the new size
  264.         mBaseWindow->SetSize( widthIn, heightIn, repaintIn );
  265.  
  266.         return PR_TRUE;
  267.     };
  268.  
  269.     return PR_FALSE;
  270. }
  271.  
  272. ////////////////////////////////////////////////////////////////////////////////
  273. // give focus to the browser so that input keyboard events work
  274. void embeddedBrowser::focusBrowser( PRBool focusBrowserIn )
  275. {
  276.     if ( focusBrowserIn )
  277.     {
  278.         nsCOMPtr< nsIWebBrowserFocus > focus( do_GetInterface( mWebBrowser ) );
  279.         focus->Activate();
  280.     }
  281.     else
  282.     {
  283.         nsCOMPtr< nsIWebBrowserFocus > focus( do_GetInterface( mWebBrowser ) );
  284.         focus->Deactivate();
  285.     };
  286. }
  287.  
  288. ////////////////////////////////////////////////////////////////////////////////
  289. //
  290. PRBool embeddedBrowser::navigateTo( const std::string uriIn )
  291. {
  292.     if ( mWebNav )
  293.     {
  294.         mWebNav->LoadURI( reinterpret_cast< const PRUnichar* >( NS_ConvertUTF8toUTF16( uriIn.c_str() ).get() ),
  295.             nsIWebNavigation::LOAD_FLAGS_NONE,
  296.                 nsnull, nsnull, nsnull );
  297.  
  298.         return PR_TRUE;
  299.     };
  300.  
  301.     return PR_FALSE;
  302. };
  303.  
  304. ////////////////////////////////////////////////////////////////////////////////
  305. //
  306. PRBool embeddedBrowser::canNavigateBack()
  307. {
  308.     if ( ! mWebNav )
  309.         return PR_FALSE;
  310.  
  311.     PRBool canGoBack = PR_FALSE;
  312.  
  313.     nsresult result = mWebNav->GetCanGoBack( &canGoBack );
  314.     if ( NS_FAILED( result ) )
  315.     {
  316.         return PR_FALSE;
  317.     };
  318.  
  319.     return canGoBack;
  320. };
  321.  
  322. ////////////////////////////////////////////////////////////////////////////////
  323. //
  324. void embeddedBrowser::navigateStop()
  325. {
  326.     if ( mWebNav )
  327.         mWebNav->Stop( nsIWebNavigation::STOP_ALL );
  328. };
  329.  
  330. ////////////////////////////////////////////////////////////////////////////////
  331. //
  332. void embeddedBrowser::navigateBack()
  333. {
  334.     if ( mWebNav )
  335.         mWebNav->GoBack();
  336. };
  337.  
  338. ////////////////////////////////////////////////////////////////////////////////
  339. //
  340. PRBool embeddedBrowser::canNavigateForward()
  341. {
  342.     if ( ! mWebNav )
  343.         return PR_FALSE;
  344.  
  345.     PRBool canGoForward = PR_FALSE;
  346.  
  347.     nsresult result = mWebNav->GetCanGoForward( &canGoForward );
  348.     if ( NS_FAILED( result ) )
  349.     {
  350.         return PR_FALSE;
  351.     };
  352.  
  353.     return canGoForward;
  354. };
  355.  
  356. ////////////////////////////////////////////////////////////////////////////////
  357. //
  358. void embeddedBrowser::navigateForward()
  359. {
  360.     if ( mWebNav )
  361.         mWebNav->GoForward();
  362. };
  363.  
  364. ////////////////////////////////////////////////////////////////////////////////
  365. // return the buffer that contains the rendered page
  366. const unsigned char* embeddedBrowser::getPageBuffer()
  367. {
  368.     return mPageBuffer;
  369. }
  370.  
  371. ////////////////////////////////////////////////////////////////////////////////
  372. // higher level mouse event
  373. void embeddedBrowser::mouseDown( PRInt16 xPosIn, PRInt16 yPosIn )
  374. {
  375.     sendMozillaMouseEvent( NS_MOUSE_LEFT_BUTTON_DOWN, xPosIn, yPosIn );
  376. }
  377.  
  378. ////////////////////////////////////////////////////////////////////////////////
  379. // higher level mouse event
  380. void embeddedBrowser::mouseUp( PRInt16 xPosIn, PRInt16 yPosIn )
  381. {
  382.     sendMozillaMouseEvent( NS_MOUSE_LEFT_BUTTON_UP, xPosIn, yPosIn );
  383. }
  384.  
  385. ////////////////////////////////////////////////////////////////////////////////
  386. // higher level mouse event
  387. void embeddedBrowser::mouseMove( PRInt16 xPosIn, PRInt16 yPosIn )
  388. {
  389.  
  390.     sendMozillaMouseEvent( NS_MOUSE_MOVE, xPosIn, yPosIn );
  391. }
  392.  
  393. ////////////////////////////////////////////////////////////////////////////////
  394. // utility methods to set an error message so something else can look at it
  395. void embeddedBrowser::setErrorMessage( std::string errMessageIn )
  396. {
  397.     mErrorMessage = errMessageIn;
  398. };
  399.  
  400. ////////////////////////////////////////////////////////////////////////////////
  401. // utility methods to get an error message that was set earlier
  402. const std::string& embeddedBrowser::getErrorMessage()
  403. {
  404.     return mErrorMessage;
  405. };
  406.  
  407. ////////////////////////////////////////////////////////////////////////////////
  408. // synthesizes a mouse event and sends into the embedded instance
  409. PRBool embeddedBrowser::sendMozillaMouseEvent( PRInt16 eventIn, PRInt16 xPosIn, PRInt16 yPosIn )
  410. {
  411.     nsCOMPtr< nsIDocShell > docShell = do_GetInterface( mWebBrowser );
  412.     if ( ! docShell )
  413.         return PR_FALSE;
  414.  
  415.     nsCOMPtr< nsPresContext > presContext;
  416.     nsresult result = docShell->GetPresContext( getter_AddRefs( presContext ) );
  417.     if ( NS_FAILED( result ) || ( ! presContext ) )
  418.         return PR_FALSE;
  419.  
  420.     nsIViewManager* viewManager = presContext->GetViewManager();
  421.     if ( ! viewManager )
  422.         return PR_FALSE;
  423.  
  424.     nsIView* rootView;
  425.     result = viewManager->GetRootView( rootView );
  426.     if ( NS_FAILED( result ) || ( ! rootView ) )
  427.         return PR_FALSE;
  428.  
  429.     nsCOMPtr< nsIWidget > widget = rootView->GetWidget();
  430.     if ( ! widget )
  431.         return PR_FALSE;
  432.  
  433.     nsMouseEvent mouseEvent( PR_TRUE, eventIn, widget, nsMouseEvent::eReal );
  434.     mouseEvent.clickCount = 1;
  435.     mouseEvent.isShift = 0;
  436.     mouseEvent.isControl = 0;
  437.     mouseEvent.isAlt = 0;
  438.     mouseEvent.isMeta = 0;
  439.     mouseEvent.widget = widget;
  440.     mouseEvent.nativeMsg = nsnull;
  441.     mouseEvent.point.x = xPosIn;
  442.     mouseEvent.point.y = yPosIn;
  443.     mouseEvent.refPoint.x = xPosIn;
  444.     mouseEvent.refPoint.y = yPosIn;
  445.     mouseEvent.flags = 0;
  446.  
  447.     nsEventStatus status;
  448.     result = viewManager->DispatchEvent( &mouseEvent, &status );
  449.     if ( NS_FAILED( result ) )
  450.         return PR_FALSE;
  451.  
  452.     return PR_TRUE;
  453. };
  454.  
  455. ////////////////////////////////////////////////////////////////////////////////
  456. // higher level keyboard function
  457. void embeddedBrowser::keyPress( PRInt16 keyCode )
  458. {
  459.     sendMozillaKeyboardEvent( 0, keyCode );
  460. }
  461.  
  462. ////////////////////////////////////////////////////////////////////////////////
  463. // synthesizes a keyboard event and sends into the embedded instance
  464. PRBool embeddedBrowser::sendMozillaKeyboardEvent( PRUint32 keyIn, PRUint32 ns_vk_code )
  465. {
  466.     nsresult result = NS_OK;
  467.  
  468.     nsCOMPtr< nsIDocShell > docShell = do_GetInterface( mWebBrowser );
  469.     if ( ! docShell )
  470.         return PR_FALSE;
  471.  
  472.     nsCOMPtr< nsPresContext > presContext;
  473.     docShell->GetPresContext( getter_AddRefs( presContext ) );
  474.     if ( ! presContext )
  475.         return PR_FALSE;
  476.  
  477.     nsIViewManager* viewManager = presContext->GetViewManager();
  478.     if ( ! viewManager )
  479.         return PR_FALSE;
  480.  
  481.     nsIView* rootView;
  482.     viewManager->GetRootView( rootView );
  483.     if ( ! rootView )
  484.         return PR_FALSE;
  485.  
  486.     nsCOMPtr< nsIWidget > widget = rootView->GetWidget();
  487.     if ( ! widget )
  488.         return PR_FALSE;
  489.  
  490.     nsKeyEvent keyEvent( PR_TRUE, NS_KEY_PRESS, widget );
  491.     keyEvent.keyCode = ns_vk_code;
  492.     keyEvent.charCode = keyIn;
  493.     keyEvent.isChar = PR_TRUE;
  494.     keyEvent.isShift = 0;
  495.     keyEvent.isControl = 0;
  496.     keyEvent.isAlt = 0;
  497.     keyEvent.isMeta = 0;
  498.     keyEvent.widget = widget;
  499.     keyEvent.nativeMsg = nsnull;
  500.     keyEvent.point.x = 0;
  501.     keyEvent.point.y = 0;
  502.     keyEvent.refPoint.x = 0;
  503.     keyEvent.refPoint.y = 0;
  504.     keyEvent.flags = 0;
  505.  
  506.     nsEventStatus status;
  507.     result = viewManager->DispatchEvent( &keyEvent, &status );
  508.     if ( NS_FAILED( result ) )
  509.         return PR_FALSE;
  510.  
  511.     return PR_TRUE;
  512. }
  513.  
  514. ////////////////////////////////////////////////////////////////////////////////
  515. // all this just to render a caret!
  516. PRBool embeddedBrowser::renderCaret()
  517. {
  518.     nsCOMPtr< nsIWebBrowserFocus > focus = do_QueryInterface( mWebBrowser );
  519.  
  520.     nsCOMPtr< nsIDOMElement > focusedElement;
  521.     focus->GetFocusedElement( getter_AddRefs( focusedElement ) );
  522.     if ( ! focusedElement )
  523.         return NS_ERROR_FAILURE;
  524.  
  525.     nsCOMPtr<nsIContent> focusedContent = do_QueryInterface( focusedElement );
  526.  
  527.     nsCOMPtr< nsIDOMWindow > domWindow;
  528.     mWebBrowser->GetContentDOMWindow( getter_AddRefs( domWindow ) );
  529.     if ( ! domWindow )
  530.         return NS_ERROR_FAILURE;
  531.  
  532.     nsCOMPtr< nsIDOMDocument > domDocument;
  533.     domWindow->GetDocument( getter_AddRefs( domDocument ) );
  534.     if ( ! domDocument )
  535.         return NS_ERROR_FAILURE;
  536.  
  537.     nsCOMPtr< nsIDocument> document = do_QueryInterface( domDocument );
  538.     if ( ! document )
  539.         return NS_ERROR_FAILURE;
  540.  
  541.     nsIPresShell* presShell = document->GetShellAt( 0 );
  542.     if ( ! presShell )
  543.         return NS_ERROR_FAILURE;
  544.  
  545.     nsCOMPtr< nsICaret > caret;
  546.     presShell->GetCaret( getter_AddRefs( caret ) );
  547.  
  548.     nsIFrame* frame = nsnull;
  549.     presShell->GetPrimaryFrameFor( focusedContent, &frame );
  550.     if ( ! frame )
  551.         return NS_ERROR_FAILURE;
  552.  
  553.     nsCOMPtr<nsISelectionController> selCtrl;
  554.     frame->GetSelectionController( presShell->GetPresContext(), getter_AddRefs( selCtrl ) );
  555.  
  556.     nsCOMPtr<nsISelection> selection;
  557.     selCtrl->GetSelection( nsISelectionController::SELECTION_NORMAL, getter_AddRefs( selection ) );
  558.  
  559.     PRBool collapsed;
  560.     nsRect coords;
  561.     nsIView* caretView;
  562.     caret->GetCaretCoordinates( nsICaret::eTopLevelWindowCoordinates, selection, &coords, &collapsed, &caretView );
  563.  
  564.     float twips2Pixls = presShell->GetPresContext()->TwipsToPixels();
  565.  
  566.     PRInt32 caretX = NSTwipsToIntPixels( coords.x, twips2Pixls );
  567.     PRInt32 caretY = NSTwipsToIntPixels( coords.y, twips2Pixls );
  568.     PRInt32 caretHeight = NSTwipsToIntPixels( coords.height, twips2Pixls );
  569.  
  570.     if ( caretX > -1 && caretX < mBrowserWidth && caretY > -1 && caretY < mBrowserHeight )
  571.     {
  572.         if ( mPageBuffer )
  573.         {
  574.             for( int y = 1; y < caretHeight - 1; ++y )
  575.             {
  576.                 mPageBuffer[ ( caretY + y ) * getBrowserRowSpan() + ( caretX + 1 ) * mBrowserDepth + 0 ] = 0;
  577.                 mPageBuffer[ ( caretY + y ) * getBrowserRowSpan() + ( caretX + 1 ) * mBrowserDepth + 1 ] = 0;
  578.                 mPageBuffer[ ( caretY + y ) * getBrowserRowSpan() + ( caretX + 1 ) * mBrowserDepth + 2 ] = 0;
  579.             };
  580.         };
  581.     };
  582.  
  583.     return NS_OK;
  584. }
  585.  
  586. ////////////////////////////////////////////////////////////////////////////////
  587. // grabs the window and writes it to a chunk of memory
  588. PRBool embeddedBrowser::grabWindow()
  589. {
  590.     nsCOMPtr< nsIDocShell > docShell = do_GetInterface( mWebBrowser );
  591.     if ( ! docShell )
  592.         return PR_FALSE;
  593.  
  594.     nsCOMPtr< nsPresContext > presContext;
  595.     nsresult result = docShell->GetPresContext( getter_AddRefs( presContext ) );
  596.     if ( NS_FAILED( result ) || ( ! presContext ) )
  597.         return PR_FALSE;
  598.  
  599.     nsIViewManager* viewManager = presContext->GetViewManager();
  600.     if ( ! viewManager )
  601.         return PR_FALSE;
  602.  
  603.     nsIScrollableView* scrollableView;
  604.     viewManager->GetRootScrollableView( &scrollableView );
  605.  
  606.     nsIView* view;
  607.     if ( scrollableView )
  608.         scrollableView->GetScrolledView( view );
  609.     else
  610.         viewManager->GetRootView( view );
  611.  
  612.     nsRect rect = view->GetBounds() - view->GetPosition() - view->GetPosition();
  613.     if ( rect.IsEmpty() )
  614.         return NS_ERROR_FAILURE;
  615.  
  616.     float p2t = presContext->PixelsToTwips();
  617.     rect.width = NSIntPixelsToTwips( mBrowserWidth, p2t );
  618.     rect.height = NSIntPixelsToTwips( mBrowserHeight, p2t );
  619.  
  620.     nsCOMPtr< nsIRenderingContext > context;
  621.     result = viewManager->RenderOffscreen( view, rect, PR_FALSE, PR_FALSE, NS_RGB( 255, 255, 255 ), getter_AddRefs( context ) );
  622.     if ( NS_FAILED( result ) )
  623.         return NS_ERROR_FAILURE;
  624.  
  625.     nsIDrawingSurface* surface = nsnull;
  626.     context->GetDrawingSurface( &surface );
  627.     if ( ! surface )
  628.         return NS_ERROR_FAILURE;
  629.  
  630.     float t2p = presContext->TwipsToPixels();
  631.     PRInt32 width = NSTwipsToIntPixels( rect.width, t2p );
  632.     PRInt32 height = NSTwipsToIntPixels( rect.height, t2p );
  633.  
  634.     PRUint8* data;
  635.     PRInt32 rowLen;
  636.  
  637.     // sometime rowspan ! width in pixels * bytes per pixel so save row span value and use in application
  638.     result = surface->Lock( 0, 0, width, height, reinterpret_cast< void** >( &data ), &mBrowserRowSpan, &rowLen, NS_LOCK_SURFACE_READ_ONLY );
  639.     if ( NS_FAILED ( result ) )
  640.         return NS_ERROR_FAILURE;
  641.  
  642.     PRUint32 bytesPerPix = rowLen / width;
  643.     nsPixelFormat format;
  644.     surface->GetPixelFormat( &format );
  645.     mBrowserDepth = bytesPerPix;
  646.  
  647.     // create it here so it can be deleted and recreated elsewhere
  648.     if ( ! mPageBuffer )
  649.         mPageBuffer = new unsigned char[ mBrowserRowSpan * mBrowserHeight ];
  650.  
  651.     memcpy( mPageBuffer, data, mBrowserRowSpan * mBrowserHeight );
  652.  
  653.     surface->Unlock();
  654.     context->DestroyDrawingSurface( surface );
  655.  
  656.     renderCaret();
  657.  
  658.     return NS_OK;
  659. }